﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Net;
using System.Xml;
using System.Web.Script.Serialization;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;


namespace GoogleMaps
{
    public class GoogleLookup
    {
        public List<AddressResult> AddressResults = new List<AddressResult>();

        #region Constructor

        public GoogleLookup(string street, string city, string state)
        {
            //Get JSON
            WebClient webClient = new WebClient();
            string json = webClient.DownloadString(String.Format("http://maps.googleapis.com/maps/api/geocode/json?address={0}+{1},+{2}&sensor=true", street, city, state));            

            //Map JSON to Classes
            JavaScriptSerializer jSerializer = new JavaScriptSerializer();
            var jsonData = jSerializer.Deserialize<GoogleGeoCodeResponse>(json);

            //Parse JSON
            foreach (Result result in jsonData.results)
            {
                var tempAddress = new AddressResult();

                tempAddress.Lat = float.Parse(result.geometry.location.lat);
                tempAddress.Lng = float.Parse(result.geometry.location.lng);

                /*
                //Need to account for multiple results b/c json formed differently
                if (result.partial_match == false)
                {
                    
                    tempAddress.PartialMatch = false;

                    string[] formattedAddress = result.formatted_address.Split(new char[] { ',' });
                    tempAddress.Street = formattedAddress[0].Trim();
                    tempAddress.City = formattedAddress[1].Trim();
                    tempAddress.State = formattedAddress[2].Substring(1, 2);
                    tempAddress.Zip = formattedAddress[2].Substring(4).Trim();

                    AddressResults.Add(tempAddress);
                    
                    break;
                     
                }
                
                tempAddress.PartialMatch = true;
                */

                //If there is no exact match...
                foreach (Address_Components detail in result.address_components)
                {
                    foreach (string type in detail.types)
                    {
                        switch (type)
                        {
                            case "street_number":
                                tempAddress.Street = detail.long_name.Trim();
                                break;
                            case "route":
                                tempAddress.Street += " " + detail.long_name.Trim();
                                break;
                            case "locality":
                                tempAddress.City = detail.long_name;
                                break;
                            case "administrative_area_level_1":
                                tempAddress.State = detail.short_name;
                                break;
                            case "postal_code":
                                tempAddress.Zip = detail.short_name;
                                break;
                        }
                    }
                }

                if (tempAddress.City != null &&
                    tempAddress.State != null &&
                    tempAddress.Zip != null &&
                    tempAddress.Street != null)
                {
                    AddressResults.Add(tempAddress);
                }
            }
        }

        #endregion

        #region Objects

        public class AddressResult
        {
            //public bool PartialMatch { get; set; }
            public float Lat { get; set; }
            public float Lng { get; set; }
            public string Street { get; set; }
            public string City { get; set; }
            public string State { get; set; }
            public string Zip { get; set; }
        }

        //JSON Mapping
        public class GoogleGeoCodeResponse
        {
            public string status { get; set; }
            public Result[] results { get; set; }
        }

        public class Result
        {
            public string[] types { get; set; }
            public string formatted_address { get; set; }
            public Address_Components[] address_components { get; set; }
            public Geometry geometry { get; set; }
            //public bool partial_match { get; set; }
        }

        public class Address_Components
        {
            public string long_name { get; set; }
            public string short_name { get; set; }
            public string[] types { get; set; }
        }

        public class Geometry
        {
            public LatLng location { get; set; }
            public string location_type { get; set; }
            public ViewPort viewport { get; set; }
            public Bounds bounds { get; set; }
        }

        public class LatLng
        {
            public string lat { get; set; }
            public string lng { get; set; }
        }

        public class ViewPort
        {
            public LatLng southwest { get; set; }
            public LatLng northeast { get; set; }
        }

        public class Bounds
        {
            public LatLng southest { get; set; }
            public LatLng northeast { get; set; }
        }

        #endregion
    }
}